package com.toplabs.unashu.controller;


import cn.hutool.json.JSONUtil;
import com.toplabs.unashu.annotation.ControllerEndpoint;
import com.toplabs.unashu.common.response.CommonResponse;
import com.toplabs.unashu.common.response.ResponseStatus;
import com.toplabs.unashu.common.utils.IPUtils;
import com.toplabs.unashu.dto.*;
import com.toplabs.unashu.entity.Blog;
import com.toplabs.unashu.entity.Type;
import com.toplabs.unashu.exception.ServiceException;
import com.toplabs.unashu.service.BlogService;
import com.toplabs.unashu.service.TypeService;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.javassist.NotFoundException;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author ityanger
 * @since 2020-08-23
 */
@Slf4j
@CrossOrigin
@RestController
public class BlogController {

    private final StringRedisTemplate stringRedisTemplate;

    private final BlogService blogService;

    private final TypeService typeService;

    public BlogController(BlogService blogService, TypeService typeService, StringRedisTemplate stringRedisTemplate) {
        this.blogService = blogService;
        this.typeService = typeService;
        this.stringRedisTemplate = stringRedisTemplate;
    }

    @GetMapping("/blogs")
    public CommonResponse<PageDto<BlogQuery>> blogs(SearchBlog searchBlog) {
        if ("".equals(searchBlog.getTitle())) {
            searchBlog.setTitle(null);
        }
        if ("".equals(searchBlog.getTypeIds())) {
            searchBlog.setTypeIds(null);
        }
        PageDto<BlogQuery> pages = blogService.listBlog(searchBlog);
        if (null == pages) {
            return CommonResponse.failed();
        }
        return CommonResponse.success(pages);
    }

    @PutMapping(value = "/blogs/recom", produces = {"application/json;charset=UTF-8"})
    @ControllerEndpoint(operation = "修改是否可评论和是否推荐", exceptionMessage = "修改评论或推荐失败")
    public CommonResponse<Boolean> updateRecCom(@RequestBody RecCom recCom) {
        log.info("{}", recCom);
        int res = blogService.updateRecCom(recCom);
        if (res == 0) {
            return CommonResponse.failed();
        }
        return CommonResponse.success(true);
    }

    @PostMapping("/blog")
    @ControllerEndpoint(operation = "保存博客", exceptionMessage = "保存博客失败")
    public CommonResponse<String> addBlog(@RequestBody Blog blog) {
        log.info("{}", blog);
        int res = blogService.saveBlog(blog);
        if (res == 0) {
            throw new ServiceException("添加失败！请重试！");
        }
        return CommonResponse.success("添加成功");
    }

    @GetMapping({"/blog/draft/{id}", "/blog/draft"})
    public CommonResponse<Blog> draftBlog(@PathVariable(value = "id", required = false) Long id) {
        return CommonResponse.success(blogService.getDraft(id));
    }

    @GetMapping("/blog/total")
    public CommonResponse<Integer> countBlog(SearchBlog searchBlog) {
        if ("".equals(searchBlog.getTitle())) {
            searchBlog.setTitle(null);
        }
        if ("".equals(searchBlog.getTypeIds())) {
            searchBlog.setTypeIds(null);
        }
        int res = blogService.countBlog(searchBlog);
        return CommonResponse.success(res);
    }

    @DeleteMapping("/blog/{id}")
    @ControllerEndpoint(operation = "根据ID删除博客", exceptionMessage = "删除博客失败")
    public CommonResponse<String> deleteBlog(@PathVariable Long id) throws NotFoundException {
        int res = blogService.deleteBlog(id);
        if (res > 0) {
            return CommonResponse.success("删除成功！");
        } else {
            throw new NotFoundException("删除失败，请重试！");
        }
    }

    @GetMapping("/pageBlogs")
    public CommonResponse<PageDto<PageBlog>> getPageBlog(BlogPageable blogPageable) {
        if ("".equals(blogPageable.getQuery())) {
            blogPageable.setQuery(null);
        }
        if (StringUtils.hasText(blogPageable.getTypeName())) {
            Type type = new Type();
            type.setName(blogPageable.getTypeName());
            Type selectType = typeService.selectType(type);
            if (selectType == null) {
                return CommonResponse.failed(ResponseStatus.NOT_FOUND);
            }
            blogPageable.setTypeId(selectType.getId());
        }
        PageDto<PageBlog> pages = blogService.getPageBlog(blogPageable);
        if (null == pages) {
            return CommonResponse.failed();
        }
        return CommonResponse.success(pages);
    }

    @GetMapping("/pageBlogs/hot")
    public CommonResponse<List<RecommendHotBlog>> getHotBlog() {
        List<RecommendHotBlog> pages = blogService.getHotBlog();
        if (null == pages) {
            return CommonResponse.failed();
        }
        return CommonResponse.success(pages);
    }

    @GetMapping("/pageBlogs/recommend")
    public CommonResponse<List<RecommendHotBlog>> getRecommendBlog() {
        List<RecommendHotBlog> pages = blogService.getRecommendBlog();
        if (null == pages) {
            return CommonResponse.failed();
        }
        return CommonResponse.success(pages);
    }

    @GetMapping("/blog/{id}")
    public CommonResponse<DetailedBlog> blog(@PathVariable Long id, HttpServletRequest request) {
        String ip = IPUtils.getIpAddr(request);
        DetailedBlog detailedBlog = blogService.getDetailedBlog(id);
        String s = stringRedisTemplate.opsForValue().get("BlogViews:" + ip + ":" + id);
        if (!StringUtils.hasText(s)) {
            Integer views = detailedBlog.getViews() + 1;
            detailedBlog.setViews(views);
            blogService.updateViews(id);
            stringRedisTemplate.opsForValue().set("BlogDetailed:" + id, JSONUtil.toJsonStr(detailedBlog));
            stringRedisTemplate.opsForValue().set("BlogViews:" + ip + ":" + id, views.toString(), 1, TimeUnit.MINUTES);
        }
        return CommonResponse.success(detailedBlog);
    }

    @GetMapping("/getSortList")
    public CommonResponse<List<String>> getSortList() {
        List<String> list = blogService.getBlogTimeSortList();
        if (list == null) {
            return CommonResponse.failed();
        }
        return CommonResponse.success(list);
    }

    @GetMapping("/getArticleByMonth")
    public CommonResponse<List<ArchivesBlog>> getArticleByMonth(String monthDate) {
        List<ArchivesBlog> list = blogService.getArticleByMonth(monthDate);
        if (list == null) {
            return CommonResponse.failed();
        }
        return CommonResponse.success(list);
    }
}